﻿using SPSDeploy.Extensions;
using SPSDeploy.Extensions.Controllers;
using System;
using System.Collections.Generic;

namespace SPSDeploy
{
    /// <summary>
    /// Main application class
    /// </summary>
    class Program
    {

        /// <summary>
        /// Appplication entry point
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Tools.DisplayInformation("*** SPS Deploy ***");
            Tools.DisplayInformation();
            try
            {
                string extractFile = null;
                string compareFile = null;
                OptionSet options = new OptionSet()
                {
                    "Usage: SPSDeploy <Command> [Options]",
                    "",
                    "Commands:",
                    "  Extract                    Extract configuration",
                    "  Compare                    Compare configuration",
                    "  Update                     Update configuration",
                    "",
                    "Options:",
                    {"e|ExtractFile=", "Specifies extract configuration file {name}", v => extractFile = v},
                    {"c|CompareFile=", "Specifies compare configuration file {name}", v => compareFile = v}
                };
                List<string> commands = options.Parse(args);
                if (commands.Count == 1)
                    switch (commands[0].ToLower())
                    {
                        case "extract":
                            ValidateParameter(extractFile, "Extract configuration file name is not specified.");
                            ExecuteExtract(extractFile);
                            break;
                        case "compare":
                            ValidateParameter(extractFile, "Extract configuration file name is not specified.");
                            ValidateParameter(compareFile, "Compare configuration file name is not specified.");
                            ExecuteCompare(extractFile, compareFile);
                            break;
                        case "update":
                            ValidateParameter(compareFile, "Compare configuration file name is not specified.");
                            ExecuteUpdate(compareFile);
                            break;
                        default:
                            throw new Exception(string.Format("Invalid command '{0}' specified.", commands[0]));
                    }
                else
                    options.WriteOptionDescriptions(System.Console.Out);
            }
            catch (Exception ex)
            {
                Tools.DisplayError(ex);
                Environment.ExitCode = 2;
            }
            Tools.DisplayInformation();
        }

        #region Private Methods
        /// <summary>
        /// Validate paramter
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="errorMessage"></param>
        private static void ValidateParameter(string parameter, string errorMessage)
        {
            if (string.IsNullOrEmpty(parameter))
                throw new Exception(errorMessage);
        }

        /// <summary>
        /// Display controller message
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void controller_ProgressMessage(object sender, MessageEventArgs e)
        {
            if (e.Type == MessageType.Information)
                Tools.DisplayInformation(e.Text);
            else if (e.Type == MessageType.Warning)
            {
                Tools.DisplayWarning(e.Text);
                Environment.ExitCode = 1;
            }
        }
        #endregion

        #region Operations
        /// <summary>
        /// Execute extract operation
        /// </summary>
        /// <param name="fileName"></param>
        private static void ExecuteExtract(string fileName)
        {
            ExtractController controller = new ExtractController(fileName);
            controller.ProgressMessage += controller_ProgressMessage;
            controller.Execute();
        }

        /// <summary>
        /// Execute compare operation
        /// </summary>
        /// <param name="inputFileName"></param>
        /// <param name="outputFileName"></param>
        private static void ExecuteCompare(string inputFileName, string outputFileName)
        {
            CompareController controller = new CompareController(inputFileName, outputFileName);
            controller.ProgressMessage += controller_ProgressMessage;
            controller.Execute();
        }

        /// <summary>
        /// Execute update operation
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="outputFileName"></param>
        private static void ExecuteUpdate(string fileName)
        {
            UpdateController controller = new UpdateController(fileName);
            controller.ProgressMessage += controller_ProgressMessage;
            controller.Execute();
        }
        #endregion

    }
}